#include "../util/TcpListener.h"
#include "../dsm/Dsm.h"
#include "Types.h"
#include <stdlib.h>
#include "colors.h"

#define BUFFER_SIZE 1024

PracticaCaso::DsmDriver * driver;

extern "C" {
	#include </usr/include/signal.h>
	#include <sys/time.h>
}

void usage() {
	cout << "Usage: DsmTimeServer <dsm-server-port>" << endl;
	exit(1);
}

void ctrl_c(int)
{
	printf("\nCTRL-C was pressed...\n");
	driver->dsm_free("BOARD");
	driver->dsm_free("TURN");
	driver->dsm_free("CONTROL");
	driver->dsm_free("PLAYER_NUM");
	delete driver;
	exit(0);
}

void showBoard(Board b)
{
	for(int i = 0; i < 9; i++)
	{
		for(int j = 0; j < 9; j++)
		{
			if(b[i][j].treasure == true)
				cout << "T  ";
			else
				cout << b[i][j].around << " ";
		}
		cout << endl;
	}
}


void initBoard(Board &b)
{

int number1;
int number2;

	for(int i = 0; i < 9; i++)
	{
		for(int j = 0; j < 9; j++)
		{
			b[i][j].opened = false;
			b[i][j].treasure = false;
		}
	}
	for(int i = 0; i < 10; i++) // puts the treasure in a random place
	{
		srand(time(0));
		number1 = rand() % 8;
		number2 = rand() % 8;
		b[number1][number2].treasure = true;
	}
	for(int i = 0; i < 9; i++) // Finds the treasure.
	{
		for(int j = 0; j < 9; j++)
		{
			if (i < number1)
			{
				if (j < number2)
					b[i][j].around = "U "; // UP: its in some upper place of X and Y
				else if (j > number2)
						b[i][j].around = "B "; // BAD: its in another line of X and Y
				else // j== number 2
					b[i][j].around = "G "; // GOOD: it's in the same line of Y
			}
			else if (i > number1)
			{
				if (j > number2)
					b[i][j].around = "D "; // DOWN: its in some upper place of X and Y
				else if (j < number2)
						b[i][j].around = "B "; // BAD: its in another line of X and Y
				else // j== number 2
					b[i][j].around = "G "; // GOOD: it's in the same line of Y
			}
			if (i == number1)
				b[i][j].around = "G "; // GOOD: it's in the same line of Y
		}
	}
}

int main(int argc, char** argv) {

	signal(SIGINT,ctrl_c);
	if (argc != 2) {
		usage();
	}

	// Hacer lookup dsm.deusto.es 
	driver = new PracticaCaso::DsmDriver("127.0.0.1", atoi(argv[1]), "dsm.deusto.es");
	PracticaCaso::DsmData data;
	driver->get_nid();
	//Game Variables
	while(1)
	{
		bool game = true;
		Board board;
		int turn = 0;
		int playerNum = 0;
		int control = 0;  //NORMAL = 0 |  WIN = 1 | FAILED = 2
		Move m;
		//End Game Variables

		initBoard(board);
		cout << "Board Initialized" << endl;
		showBoard(board);

		//showBoard(board);
		try {
		
			driver->dsm_malloc("BOARD", sizeof(board)); //Board Malloc
			cout << "Malloc of Board done..." << endl;
			driver->dsm_malloc("TURN", sizeof(turn)); //Turn Malloc
			cout << "Malloc of Turn done..." << endl;
			driver->dsm_malloc("PLAYER_NUM", sizeof(playerNum)); //PlayerNum Malloc
			cout << "Malloc of PlayerNum done..." << endl;
			driver->dsm_malloc("CONTROL", sizeof(board)); //Board Malloc
			cout << "Malloc of Control done..." << endl;

			driver->dsm_put("BOARD", (void *)board, sizeof(board));
			driver->dsm_put("TURN", (void *)&turn, sizeof(turn));
			driver->dsm_put("PLAYER_NUM", (void *)&playerNum, sizeof(playerNum));
			driver->dsm_put("CONTROL", (void *)&control, sizeof(control));		

			do
			{
				driver->dsm_wait("PLAYER_NUM");
				data = driver->dsm_get("PLAYER_NUM");
				playerNum = *((int* )data.addr);
			}while(playerNum != 2);
	
			turn = 1; //The Game Starts Here
			driver->dsm_put("PLAYER_NUM",(void *)&playerNum, sizeof(playerNum)); //The Servers PUTs the variable so it can do the FREE Later
			cout << "The 2 Players are ready, let's start the game!" << endl;
			game = true;
			control = 0;
			while(game)
			{
				if(turn == 1)
				{
					driver->dsm_put("TURN", (void *)&turn, sizeof(turn));
					if(control == 1 || control == 2)
					{
						cout << "Game Over" << endl;
						cout << "Finishing Process" << endl;
						sleep(5);
						game = false;
						driver->dsm_free("BOARD");
						driver->dsm_free("TURN");
						driver->dsm_free("CONTROL");
						driver->dsm_free("PLAYER_NUM");
						//exit(0);
					}
					if(game) //Game = false means that the game is over
					{
						driver->dsm_wait("PLAYER1"); //Waits the Players move
						data = driver->dsm_get("PLAYER1");
						m = *((Move* )data.addr);
						turn = 2; //Changes the turn
					}
				}
				else if(turn == 2)
				{
					driver->dsm_put("TURN", (void *)&turn, sizeof(turn));
					if(control == 1 || control == 2)
					{
						cout << "Game Over" << endl;
						cout << "Finishing Process" << endl;
						sleep(5);
						game = false;
						driver->dsm_free("BOARD");
						driver->dsm_free("TURN");
						driver->dsm_free("CONTROL");
						driver->dsm_free("PLAYER_NUM");
						//exit(0);
					}
					if(game) //Game = false meens that the game is over
					{
						driver->dsm_wait("PLAYER2");
						data = driver->dsm_get("PLAYER2");
						m = *((Move* )data.addr);
						cout << "Movement of player 2" << endl;
						turn = 1;
					}
				}
				if(game)
				{
					driver->dsm_put("BOARD", (void *)board, sizeof(board)); //Refresh the Board
					control = 0; //All is ok
					if(board[m.x][m.y].treasure == true)
						control = 1; //Treasure found
				
					int openedCounter = 0;
					for(int i = 0; i < 9; i++)
						for(int j = 0; j < 9; j++)
						{
							if(board[i][j].opened)
								openedCounter++;
						}
					if(openedCounter == 80)
						control = 2; //All boxes opened -> lose
					driver->dsm_put("CONTROL", (void *)&control, sizeof(control));
				}
			}
		
		
		} catch (DsmException dsme) {
				cerr << "ERROR: " << dsme << endl;
		}
	}
	driver->dsm_free("BOARD");
	driver->dsm_free("TURN");
	driver->dsm_free("CONTROL");
	driver->dsm_free("PLAYER_NUM");
	


		
}

